/*	Copyright(C) 27wuyin 2019 */
/*
	Using:LGPL v2.1
*/

#ifndef _TSLOG_TEST_SYMBOL_
	#define _TSLOG_TEST_SYMBOL_
	#include<stdint.h>
	#include<time.h>
	#include<stdlib.h>
	#include<math.h>

/*	logType_TYPE_TSLOG_
	_MEMORY_LOG:about memory
	_IO_LOG_:about input/output
	_INTERNET_LOG_:about Internet
	_DL_LOG_:about dyamic library
	_DB_LOG_:about data library
	_CALC_LOG_:about calc
	_OTHER_LOG_:other log
	*/
typedef enum
{
	_MEMORY_LOG_=0,_IO_LOG_,
	_INTERNET_LOG_,_DL_LOG_,
	_DB_LOG_,_CALC_LOG_,
	_OTHER_LOG_
}logType_TYPE_TSLOG_;

typedef struct
{
	char *why,*info;
	void *whereFunction;
	long long int logTime;
	char logFileName[128];
	char usingThis;
	time_t logTime_S;
	logType_TYPE_TSLOG_ type;
}logType_TS;

#define TSFUNCTIONADDR_CAST(func) ((void*)(func))

	// use this merger to cast a function adderss
	// to a interger number
#define _tsGlobalLog_Using NULL

	/* some function */
logType_TS *tsNewLogCtrl(void);
void tsThrowLog(logType_TS *log,logType_TYPE_TSLOG_ type,char *why
			   ,char *info,void *functionAddr);
void tsAutoPrintLog(logType_TS *log);
void tsGetLogInfo(logType_TS *log,logType_TYPE_TSLOG_ *logType
				 ,char *why,char *info,void **function
				 ,long long int *logTime);
void tsSetLogFile(logType_TS *log,char *name);
void tsFreeLogPtr(logType_TS *log);
int tsIsLogThrew(logType_TS *log);
void tsPrintLogStdErr(logType_TS *log);

/*
	macroName:tsCheckPointer
	input:
		log:a point to the log struct
		point:a point
	brief:Check this pointer,if its value is NULL,throw log.
*/
#define tsCheckPoint(log,point)   do{ \
	if(!(point)) \
	{ \
		tsThrowLog(log,_MEMORY_LOG_,"The pointer is NULL","Check point("#point")  and its value is NULL",NULL); \
	}}while(0)


/*
	macroName:tsCheckExpTrue
	input:
		log:a point to the log struct
		exp:an expression
	brief:Check this expression,if it is false,throw log.
*/
#define tsCheckExpTrue(log,exp)	do{ \
	if(!(exp)) \
		tsThrowLog(log,_CALC_LOG_,"The expression is false."\
				  ,"Check expression ("#exp") and it is false.",NULL); \
	}while(0)

/*	macroName:tsCheckFileOpen
	brief:check a pointer to a file struct and when its
	value is NULL,throw log.
	input:file:a pointer to a file struct
*/
#define tsCheckFileOpen(log,file) do{ \
	if(!file) \
	{ \
		tsThrowLog(log,_IO_LOG_,"Open a file error.","Check file struct point("#file") and its value is NULL",NULL); \
	}}while(0)

/*	macroName:tsCheckPoint_Easy
	brief:check a point.If its value is NULL,throw log and print the log.
	If macro "__TSAUTOEXIT_EASYCLASS__" defined,the program will exit with
	return value -1.
	Warning:It is different from macro "tsCheckPointer".
*/
#ifdef __TSAUTOEXIT_EASYCLASS__
#define tsCheckPoint_Easy(point) do{ \
	if(!point) \
	{ \
		tsThrowLog(_tsGlobalLog_Using,_MEMORY_LOG_,"The point\'s value is NULL","Check point("#point") and its value is NULL.The program exit with code -1",NULL); \
		tsAutoPrintLog(_tsGlobalLog_Using); \
		exit(-1);  \
	}}while(0)
#endif
#ifndef __TSAUTOEXIT_EASYCLASS__
#define tsCheckPoint_Easy(point) do{ \
	if(!point) \
	{ \
		tsThrowLog(_tsGlobalLog_Using,_MEMORY_LOG_,"The point\'s value is NULL","Check point("#point") and its value is NULL.",NULL); \
		tsAutoPrintLog(_tsGlobalLog_Using); \
	}}while(0)
#endif

/*
	Warning:Now it is not alive

	macroName:tsCheckExp_AutoExit
	input:
		log:a point to the struct of log
		exp:The expression
	brief:Use this macro to check the expression.If its value is false,
	throw log and exit this function(Warning:It is different from the macro
	"tsCheckExpTrue")
*/


/*
	macroName:tsLog_Internet_Connect & tsLog_Internet_Disconnect
	input:
		log:a point to the struct of log
		ip:the IP address of the client
	brief:Use these macro to throw log for connecting and disconnecting
*/
#define tsLog_Internet_Connect(log,ip) tsThrowLog(_tsGlobalLog_Using,_INTERNET_LOG_,"Connecting log",ip" connected this computer.",NULL)
#define tsLog_Internet_Disconnect(log,ip) tsThrowLog(_tsGlobalLog_Using,_INTERNET_LOG_,"Connecting log",ip" disconnect this computer",NULL)

/*
	macroName:tsLog_Calc_NaN
	input:
		log:a point to the struct of log
		num:The var or number with value NaN(Not a Number)
	brief:Use this macro to throw log for value NaN.
*/
#define tsCheckNaN(log,var) do{ \
	if(isnan(var)) \
	{ \
		tsThrowLog(log,_CALC_LOG_,"NaN Value","Check one varible("#var") and its value is NaN.",NULL); \
	}}while(0)


#endif